package com.holly.unit.es.api;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.ResponseEntity;

import java.util.List;
import java.util.Map;

/**
 * 接口描述: ES操作相关API
 *
 * @author fxr
 * @version 1.0.0
 * @date 2022/4/2 11:03
 */
public interface EsApi {

    /***
     * cat 查询ElasticSearch系统数据，返回json
     * @param urlAfter
     * @param responseType
     * @param <T>
     * @return
     */
     <T> ResponseEntity<T> _cat(String urlAfter, Class<T> responseType);

    /***
     * 查询所有索引
     * 查询地址：GET http://{baseUrl}/_cat/indices
     * @return
     */
     JSONArray getIndices();

    /***
     * 查询单个索引
     * @param indexName
     * 查询地址：GET http://{baseUrl}/_cat/indices/{indexName}
     * @return
     */
    JSONArray getIndices(String indexName);

    /***
     * 索引是否存在
     * @param indexName
     * @return
     */
    boolean indexExists(String indexName);

    /***
     * 根据ID获取索引数据，未查询到返回null
     * 查询地址：GET http://{baseUrl}/{indexName}/{typeName}/{dataId}
     * @param indexName 索引名称
     * @param typeName type，一个任意字符串，用于分类
     * @param dataId 数据id
     * @return
     */
    JSONObject getDataById(String indexName, String typeName, String dataId);

    /***
     * 创建索引
     *
     * 查询地址：PUT http://{baseUrl}/{indexName}
     *
     * 返回结果 （仅供参考）
        "createIndex": {
                            "shards_acknowledged": true,
                            "acknowledged": true,
                            "index": "hello_world"
                        }

     * @param indexName
     *
     * @return
     */
    boolean createIndex(String indexName);

    /***
     * 删除索引
     * 查询地址：DELETE http://{baseUrl}/{indexName}
     * @param indexName
     * @return
     */
    boolean removeIndex(String indexName);

    /**
     * 获取索引字段映射（可获取字段类型）
     * <p>
     *
     * @param indexName 索引名称
     * @param typeName  分类名称
     * @return
     */
    /*
         * 参考返回JSON结构：
         *
         *{
         *    // 索引名称
         *    "[indexName]": {
         *        "mappings": {
         *            // 分类名称
         *            "[typeName]": {
         *                "properties": {
         *                    // 字段名
         *                    "input_number": {
         *                        // 字段类型
         *                        "type": "long"
         *                    },
         *                    "input_string": {
         *                        "type": "text",
         *                        "fields": {
         *                            "keyword": {
         *                                "type": "keyword",
         *                                "ignore_above": 256
         *                            }
         *                        }
         *                    }
         *                 }
         *            }
         *        }
         *    }
         * }
         */
    JSONObject getIndexMapping(String indexName, String typeName);

    /**
     * 获取索引字段映射，返回Java实体类
     *
     * @param indexName
     * @param typeName
     * @return
     */
    <T> Map<String, T> getIndexMappingFormat(String indexName, String typeName, Class<T> clazz);

    /**
     * 保存数据，详见：saveOrUpdate
     */
    boolean save(String indexName, String typeName, String dataId, JSONObject data);

    /**
     * 更新数据，详见：saveOrUpdate
     */
    boolean update(String indexName, String typeName, String dataId, JSONObject data);

    /**
     * 保存或修改索引数据
     * <p>
     * 查询地址：PUT http://{baseUrl}/{indexName}/{typeName}/{dataId}
     *
     * @param indexName 索引名称
     * @param typeName  type，一个任意字符串，用于分类
     * @param dataId    数据id
     * @param data      要存储的数据
     * @return
     */

    /* 返回结果（仅供参考）
       "createIndexA2": {
            "result": "created",
            "_shards": {
                "total": 2,
                "successful": 1,
                "failed": 0
            },
            "_seq_no": 0,
            "_index": "test_index_1",
            "_type": "test_type_1",
            "_id": "a2",
            "_version": 1,
            "_primary_term": 1
        }
     */
    boolean saveOrUpdate(String indexName, String typeName, String dataId, JSONObject data);


    /**
     * 删除索引数据
     * <p>
     * 请求地址：DELETE http://{baseUrl}/{indexName}/{typeName}/{dataId}
     */

    /* 返回结果（仅供参考）
        {
            "_index": "es_demo",
            "_type": "docs",
            "_id": "001",
            "_version": 3,
            "result": "deleted",
            "_shards": {
                "total": 1,
                "successful": 1,
                "failed": 0
            },
            "_seq_no": 28,
            "_primary_term": 18
        }
    */
    boolean delete(String indexName, String typeName, String dataId);

    /**
     * 查询数据
     * <p>
     * 请求地址：POST http://{baseUrl}/{indexName}/{typeName}/_search
     */
    JSONObject search(String indexName, String typeName, JSONObject queryObject);

    /**
     * 查询构建器
     * @param _source （源滤波器）指定返回的字段，传null返回所有字段
     * @param query
     * @param from    从第几条数据开始
     * @param size    返回条目数
     * @return { "query": query }
     */
    JSONObject buildQuery(List<String> _source, JSONObject query, int from, int size);

    /**
     * @return { "bool" : { "must": must, "must_not": mustNot, "should": should } }
     */
    JSONObject buildBoolQuery(JSONArray must, JSONArray mustNot, JSONArray should);

    /**
     * @param field 要查询的字段
     * @param args  查询参数，参考： *哈哈* OR *哒* NOT *呵* OR *啊*
     * @return
     */
    JSONObject buildQueryString(String field, String... args);

    /**
     * @return { "query_string": { "query": query }  }
     */
    JSONObject buildQueryString(String query);

    /**
     * @param field      查询字段
     * @param min        最小值
     * @param max        最大值
     * @param containMin 范围内是否包含最小值
     * @param containMax 范围内是否包含最大值
     * @return { "range" : { field : { 『 "gt『e』?containMin" : min 』?min!=null , 『 "lt『e』?containMax" : max 』}} }
     */
    JSONObject buildRangeQuery(String field, Object min, Object max, boolean containMin, boolean containMax);





}
